package org.zjx.operate;

import com.sun.jna.platform.win32.BaseTSD;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinUser;
import lombok.SneakyThrows;
import org.zjx.entity.Rect;
import org.zjx.window.GameWindow;

import java.awt.*;
import java.awt.image.BufferedImage;

public class GameOperate implements IOperate {
    public static final int WM_MOUSEMOVE = 0x200;
    public static final int WM_LBUTTONDOWN = 0x0201;
    public static final int WM_LBUTTONUP = 0x0202;
    public static final int WM_RBUTTONDOWN = 0x0204;  // 右键按下
    public static final int WM_RBUTTONUP = 0x0205;    // 右键抬起
    public static final int WM_MOUSEWHEEL = 0x020A; //中键滑动
    public static final int WHEEL_DELTA = 120; //中键滑动 单位

    private final GameWindow gameWindow;

    public GameOperate(GameWindow gameWindow) {
        this.gameWindow = gameWindow;
    }

    @SneakyThrows
    @Override
    public BufferedImage getImage(Rect rect) {
        Rect screen = gameWindow.getTrueBounds();
        return RobotOperate.getInstance().getImage(new Rect(screen.getLeft() + rect.getLeft(), screen.getTop() + rect.getTop(), screen.getLeft() + rect.getRight(), screen.getTop() + rect.getBottom()));
    }

    @SneakyThrows
    @Override
    public Color getPixelColor(int x, int y) {
        Rect screen = gameWindow.getTrueBounds();
        return RobotOperate.getInstance().getPixelColor(x + screen.getLeft(), y + screen.getTop());
    }

    @Override
    public void moveMouse(int x, int y) {
        gameWindow.setMouseNow(new Point(x, y));
        User32.INSTANCE.SendMessage(gameWindow.getHwnd(), WM_MOUSEMOVE, new WinDef.WPARAM(0), new WinDef.LPARAM(((long) y << 16) | (x & 0xFFFF)));
    }

    @Override
    public void clickMouse(Point point) {
        moveMouse(point.x, point.y);
        delay(30);
        clickMouse(1);
    }

    @Override
    public void clickMouse(int button) {
        clickMouse(button, MouseAction.DOWN);
        delay(10);
        clickMouse(button, MouseAction.UP);
    }

    @Override
    public void clickMouse(int button, MouseAction action) {
        int message = button == 1
                ? (action == MouseAction.DOWN ? WM_LBUTTONDOWN : WM_LBUTTONUP)
                : (action == MouseAction.DOWN ? WM_RBUTTONDOWN : WM_RBUTTONUP);

        User32.INSTANCE.SendMessage(gameWindow.getHwnd(), message, new WinDef.WPARAM(0), null);
    }

    @Override
    public void scrollMouse(int amount) {
        // Ensure the window is in the correct state before sending the message

        // 计算滚轮偏移量（必须是WHEEL_DELTA的倍数）
        int wheelMovement = amount * WHEEL_DELTA;
        // 构造wParam：高16位=滚轮偏移量，低16位=虚拟按键状态（0表示无按键）
        long wParamValue = ((long) wheelMovement << 16) & 0xFFFF0000L;
        WinDef.WPARAM wParam = new WinDef.WPARAM(wParamValue);

        WinDef.LPARAM lParam = new WinDef.LPARAM(0);  // We don't need to move the cursor, so we use 0

        // Send the message to simulate the mouse wheel scrolling
        User32.INSTANCE.SendMessage(gameWindow.getHwnd(), WM_MOUSEWHEEL, wParam, lParam);
    }


    @Override
    public void dragMouse(int startX, int startY, int endX, int endY) {
        moveMouse(startX, startY); // 移动到起始位置
        // 按下左键开始拖动
        clickMouse(1, MouseAction.DOWN);
        // 持续移动鼠标到目标位置
        moveMouse(endX, endY);
        // 松开左键完成拖动
        clickMouse(1, MouseAction.UP);
    }

    @Override
    public void write(String str) {
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            this.sendChar(c);
            this.delay(100);
        }
    }

    @SneakyThrows
    @Override
    public void pressKeyCombination(int... keyCodes) {
        RobotOperate.getInstance().pressKeyCombination(keyCodes);
    }

    @Override
    public void delay(int millis) {
        RobotOperate.getInstance().delay(millis);
    }

    private static final WinUser.INPUT input = new WinUser.INPUT();

    private void sendChar(char ch) {
        input.type = new WinDef.DWORD(1L);
        input.input.setType("ki");
        input.input.ki.wScan = new WinDef.WORD(0L);
        input.input.ki.time = new WinDef.DWORD(0L);
        input.input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0L);

        // 对于ASCII字符，使用常规方式
        boolean needsShift = false;
        int virtualKey = 0;

        // 处理 Unicode 字符
        if (ch > 255) {
            // 对于非ASCII字符，使用虚拟键码0（VK_PACKET）
            input.input.ki.wVk = new WinDef.WORD(0);
            input.input.ki.wScan = new WinDef.WORD(ch);
            input.input.ki.dwFlags = new WinDef.DWORD(0x0004); // KEYEVENTF_UNICODE
        } else {
            // 处理特殊字符
            switch (ch) {
                case '~':
                    needsShift = true;
                    virtualKey = 192;
                    break; // `键
                case '!':
                    needsShift = true;
                    virtualKey = 49;
                    break;  // 1键
                case '@':
                    needsShift = true;
                    virtualKey = 50;
                    break;  // 2键
                case '#':
                    needsShift = true;
                    virtualKey = 51;
                    break;  // 3键
                case '$':
                    needsShift = true;
                    virtualKey = 52;
                    break;  // 4键
                case '%':
                    needsShift = true;
                    virtualKey = 53;
                    break;  // 5键
                case '^':
                    needsShift = true;
                    virtualKey = 54;
                    break;  // 6键
                case '&':
                    needsShift = true;
                    virtualKey = 55;
                    break;  // 7键
                case '*':
                    needsShift = true;
                    virtualKey = 56;
                    break;  // 8键
                case '(':
                    needsShift = true;
                    virtualKey = 57;
                    break;  // 9键
                case ')':
                    needsShift = true;
                    virtualKey = 48;
                    break;  // 0键
                case '_':
                    needsShift = true;
                    virtualKey = 189;
                    break; // -键
                case '+':
                    needsShift = true;
                    virtualKey = 187;
                    break; // =键
                case '{':
                    needsShift = true;
                    virtualKey = 219;
                    break; // [键
                case '}':
                    needsShift = true;
                    virtualKey = 221;
                    break; // ]键
                case '|':
                    needsShift = true;
                    virtualKey = 220;
                    break; // \键
                case ':':
                    needsShift = true;
                    virtualKey = 186;
                    break; // ;键
                case '"':
                    needsShift = true;
                    virtualKey = 222;
                    break; // '键
                case '<':
                    needsShift = true;
                    virtualKey = 188;
                    break; // ,键
                case '>':
                    needsShift = true;
                    virtualKey = 190;
                    break; // .键
                case '?':
                    needsShift = true;
                    virtualKey = 191;
                    break; // /键
                case ' ':
                    virtualKey = 32;
                    break; // 空格键
                case '\t':
                    virtualKey = 9;
                    break; // 制表符
                case '\n':
                    virtualKey = 13;
                    break; // 回车键
                case '.':
                    virtualKey = 190;
                    break; // 点号
                default:
                    if (Character.isUpperCase(ch)) {
                        needsShift = true;
                        virtualKey = Character.toUpperCase(ch);
                    } else {
                        virtualKey = Character.toUpperCase(ch);
                    }
            }

            if (needsShift) {
                pressKey(16, true); // 按下Shift
                this.delay(30);
            }

            input.input.ki.wVk = new WinDef.WORD((long) virtualKey);
            input.input.ki.dwFlags = new WinDef.DWORD(0L);
        }

        User32.INSTANCE.SendInput(new WinDef.DWORD(1L), (WinUser.INPUT[]) input.toArray(1), input.size());
        input.input.ki.dwFlags = new WinDef.DWORD(2L); // KEYEVENTF_KEYUP
        User32.INSTANCE.SendInput(new WinDef.DWORD(1L), (WinUser.INPUT[]) input.toArray(1), input.size());

        if (needsShift) {
            pressKey(16, false); // 释放Shift
            this.delay(30);
        }
    }

    // 模拟按下或释放 Shift 键
    private static void pressKey(int keyCode, boolean press) {
        input.input.ki.wVk = new WinDef.WORD(keyCode);
        input.input.ki.dwFlags = press ? new WinDef.DWORD(0) : new WinDef.DWORD(2); // 按下或释放
        User32.INSTANCE.SendInput(new WinDef.DWORD(1), (WinUser.INPUT[]) input.toArray(1), input.size());
    }


}
